#!/usr/bin/env bash
# sstree — 会话/进程组/进程三层树，正确对齐并标记 FG/BG
# 用法：sstree [-a]

set -euo pipefail

# ---------- 参数 ----------
SHOW_ALL=false
[[ ${1:-} == "-a" ]] && SHOW_ALL=true

# ---------- 颜色 ----------
FG=$'\e[1;32m'   # 绿色
BG=$'\e[1;33m'   # 黄色
RST=$'\e[0m'

# ---------- 1. 取所有进程 ----------
mapfile -t L < <(
    ps -eo sid=,pgid=,pid=,tty=,comm= --sort sid,pgid,pid
)

# ---------- 2. 建立 tty -> 前台 pgid ----------
declare -A tty_tpgid
while read -r tty tpgid; do
    [[ -z $tty || $tty == "?" ]] && continue
    [[ -z ${tty_tpgid[$tty]:-} ]] && tty_tpgid[$tty]=$tpgid
done < <(ps -eo tty=,tpgid= --no-headers)

# ---------- 3. 过滤 ----------
filtered=()
for ln in "${L[@]}"; do
    read sid pgid pid tty comm <<<"$ln"
    if [[ $tty == "?" ]]; then
        $SHOW_ALL && filtered+=("$ln")
    else
        filtered+=("$ln")
    fi
done

# ---------- 4. 输出 ----------
printf '\n%-6s %-6s  %-6s  %-8s %s\n' SID PGID PID TTY CMD
#printf '%-6s %-6s  %-6s  %-8s %s\n' --- ---- --- ---- ---

prev_sid=""; prev_pgid=""

for ln in "${filtered[@]}"; do
    read sid pgid pid tty comm <<<"$ln"
    # 会话分割线
    [[ $sid != "$prev_sid" ]] && { printf '\r-------------------------------------------------\n%-6s\n' "$sid"; prev_sid=$sid; prev_pgid=""; }
    # 进程组分割线
    [[ $pgid != "$prev_pgid" ]] && {
        if [[ -n ${tty_tpgid[$tty]:-} && $pgid == ${tty_tpgid[$tty]} ]]; then
            flag="${FG}FG${RST}"
        else
            flag="${BG}BG${RST}"
        fi
        printf '       %-6s  %-6s\n' "$pgid" "$flag"
        prev_pgid=$pgid
    }
    # 进程行
    printf '               %-6s  %-6s   %s\n' "$pid" "$tty" "$comm"
done
